# Copyright 2025 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

load("@bazel_skylib//rules:copy_directory.bzl", "copy_directory")
load("@doxygen//:doxygen.bzl", "doxygen")
load("@rules_python//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
load("@rules_python//sphinxdocs:sphinx_docs_library.bzl", "sphinx_docs_library")
load("//pw_build:compatibility.bzl", "incompatible_with_mcu")

package(default_visibility = ["//visibility:public"])

licenses(["notice"])

exports_files([
    "module_metadata.json",
    "module_metadata_schema.json",
])

sphinx_docs_library(
    # TODO: https://pwbug.dev/377679855 - Rename this to "docs" after merging.
    name = "not_prefixed",
    srcs = [
        "_extensions/bug.py",
        "_extensions/kconfig.py",
        "_extensions/module_metadata.py",
        "_extensions/modules_index.py",
        "_extensions/pigweed_live.py",
        "_extensions/pw_status_codes.py",
        "_extensions/seed_metadata.py",
        "_extensions/sitemap.py",
        "automated_analysis.rst",
        "bazel_compatibility.rst",
        "build_system.rst",
        "changelog.rst",
        "index.rst",
        "module_metadata.json",
        "module_metadata_schema.json",
        "modules.rst",
        "python_build.rst",
        # TODO: b/388905812 - Delete this file.
        "size_report_notice",
        "targets.rst",
        "third_party_support.rst",
        "toolchain.rst",
    ],
    strip_prefix = "docs/",
    target_compatible_with = incompatible_with_mcu(),
)

# TODO: https://pwbug.dev/377679855 - Merge this into "not_prefixed"
# (which will be renamed to "docs" after the merge).
sphinx_docs_library(
    name = "prefixed",
    srcs = [
        "3p/index.rst",
        "_static/css/pigweed.css",
        "_static/js/changelog.js",
        "_static/js/pigweed.js",
        "blog/01-kudzu.rst",
        "blog/02-bazel-feature-flags.rst",
        "blog/03-pigweed-sdk.rst",
        "blog/04-fixed-point.rst",
        "blog/05-coroutines.rst",
        "blog/06-better-cpp-toolchains.rst",
        "blog/07-bazelcon-2024.rst",
        "blog/08-bazel-docgen.rst",
        "blog/index.rst",
        "blog/rss.xml",
        "code_of_conduct.rst",
        "code_reviews.rst",
        "community/index.rst",
        "concepts/index.rst",
        "contributing/build.rst",
        "contributing/docs/build.rst",
        "contributing/docs/changelog.rst",
        "contributing/docs/index.rst",
        "contributing/docs/modules.rst",
        "contributing/docs/website.rst",
        "contributing/index.rst",
        "embedded_cpp_guide.rst",
        "facades.rst",
        "faq.rst",
        "get_started/bazel.rst",
        "get_started/bazel_integration.rst",
        "get_started/first_time_setup.rst",
        "get_started/github_actions.rst",
        "get_started/index.rst",
        "get_started/install_bazel.rst",
        "get_started/zephyr.rst",
        "glossary.rst",
        "infra/bazel_lockfile.rst",
        "infra/ci_cq_intro.rst",
        "infra/glossary.rst",
        "infra/index.rst",
        "infra/rollers.rst",
        "layout/layout.html",
        "mission.rst",
        "module_structure.rst",
        "os/index.rst",
        "os/zephyr/index.rst",
        "os/zephyr/kconfig.rst",
        "overview.rst",
        "showcases/index.rst",
        "showcases/sense/automate.rst",
        "showcases/sense/bazel_cloud.rst",
        "showcases/sense/build.rst",
        "showcases/sense/code_intelligence.rst",
        "showcases/sense/crash_handler.rst",
        "showcases/sense/device_tests.rst",
        "showcases/sense/explore.rst",
        "showcases/sense/factory.rst",
        "showcases/sense/flash.rst",
        "showcases/sense/host_sim.rst",
        "showcases/sense/host_tests.rst",
        "showcases/sense/index.rst",
        "showcases/sense/intro.rst",
        "showcases/sense/outro.rst",
        "showcases/sense/production.rst",
        "showcases/sense/rpc.rst",
        "showcases/sense/setup.rst",
        "showcases/sense/web.rst",
        "size_optimizations.rst",
        "style/bazel.rst",
        "style/cli.rst",
        "style/commit_message.rst",
        "style/cpp.rst",
        "style/doxygen.rst",
        "style/protobuf.rst",
        "style/python.rst",
        "style/rest.rst",
        "style/writing.rst",
        "style_guide.rst",
    ],
    # TODO: https://pwbug.dev/377679855 - Remove this URL prefix.
    prefix = "docs/",
    target_compatible_with = incompatible_with_mcu(),
)

copy_directory(
    name = "rust_files",
    src = "//pw_rust:docs_dir",
    out = "rustdoc",
)

sphinx_docs_library(
    name = "rust",
    srcs = [":rust_files"],
    prefix = "rustdoc/",
    target_compatible_with = incompatible_with_mcu(),
)

filegroup(
    name = "doxygen_srcs",
    srcs = [
        "//pw_alignment:doxygen",
        "//pw_allocator:doxygen",
        "//pw_analog:doxygen",
        "//pw_async:doxygen",
        "//pw_async2:doxygen",
        "//pw_async2_basic:doxygen",
        "//pw_async_basic:doxygen",
        "//pw_base64:doxygen",
        "//pw_bloat:doxygen",
        "//pw_bluetooth:doxygen",
        "//pw_bluetooth_proxy:doxygen",
        "//pw_bluetooth_sapphire:doxygen",
        "//pw_build:doxygen",
        "//pw_bytes:doxygen",
        "//pw_channel:doxygen",
        "//pw_chre:doxygen",
        "//pw_chrono:doxygen",
        "//pw_clock_tree:doxygen",
        "//pw_clock_tree_mcuxpresso:doxygen",
        "//pw_containers:doxygen",
        "//pw_crypto:doxygen",
        "//pw_digital_io:doxygen",
        "//pw_digital_io_mcuxpresso:doxygen",
        "//pw_display:doxygen",
        "//pw_elf:doxygen",
        "//pw_function:doxygen",
        "//pw_hdlc:doxygen",
        "//pw_hex_dump:doxygen",
        "//pw_i2c:doxygen",
        "//pw_i2c_linux:doxygen",
        "//pw_interrupt:doxygen",
        "//pw_json:doxygen",
        "//pw_kvs:doxygen",
        "//pw_log:doxygen",
        "//pw_log_string:doxygen",
        "//pw_log_tokenized:doxygen",
        "//pw_malloc:doxygen",
        "//pw_multibuf:doxygen",
        "//pw_numeric:doxygen",
        "//pw_perf_test:doxygen",
        "//pw_polyfill:doxygen",
        "//pw_preprocessor:doxygen",
        "//pw_protobuf:doxygen",
        "//pw_random:doxygen",
        "//pw_rpc:doxygen",
        "//pw_span:doxygen",
        "//pw_spi:doxygen",
        "//pw_status:doxygen",
        "//pw_stream:doxygen",
        "//pw_stream_uart_linux:doxygen",
        "//pw_string:doxygen",
        "//pw_sync:doxygen",
        "//pw_sys_io:doxygen",
        "//pw_system:doxygen",
        "//pw_thread:doxygen",
        "//pw_tokenizer:doxygen",
        "//pw_toolchain:doxygen",
        "//pw_trace_tokenized:doxygen",
        "//pw_transfer:doxygen",
        "//pw_uart:doxygen",
        "//pw_unit_test:doxygen",
        "//pw_uuid:doxygen",
        "//pw_varint:doxygen",
        "//pw_work_queue:doxygen",
        "//third_party/freertos:doxygen",
    ],
)

# Run Doxygen on the gathered headers to generate XML.
doxygen(
    name = "doxygen_build",
    srcs = [
        ":doxygen_srcs",
    ],
    outs = [
        "html",
        "xml",
    ],
    # TODO: b/384047922 - Move configuration to a dedicated Doxyfile.
    configurations = [
        # Use `leading-asterisk` even though `leading-slashes` is more
        # semantically accurate (all Doxygen comments in Pigweed codebase
        # start with `///`). See the discussion about undocumented Doxygen
        # behavior at the bottom of this section:
        # https://breathe.readthedocs.io/en/latest/markups.html#aliases
        "ALIASES = \"rst=^^@verbatim embed:rst:leading-asterisk^^\"",
        "ALIASES += \"endrst=@endverbatim\"",
        "ALIASES += \"rstref{1}=@verbatim embed:rst:inline :ref:`\\1` @endverbatim\"",
        "ALIASES += \"crossref{3}=@verbatim embed:rst:inline :\\1:\\2:`\\3` @endverbatim\"",
        "ALIASES += \"c_macro{1}=@crossref{c,macro,\\1}\"",
        "ALIASES += \"cpp_class{1}=@crossref{cpp,class,\\1}\"",
        "ALIASES += \"cpp_func{1}=@crossref{cpp,func,\\1}\"",
        "ALIASES += \"cpp_type{1}=@crossref{cpp,type,\\1}\"",
        "ALIASES += \"cpp_enum{1}=@crossref{cpp,type,\\1}\"",
        "ALIASES += \"pw_status{1}=@crossref{c,enumerator,\\1}\"",
        "CASE_SENSE_NAMES = NO",
        "ENABLE_PREPROCESSING = YES",
        "EXTRACT_PACKAGE = YES",
        "EXTRACT_PRIV_VIRTUAL = YES",
        "EXTRACT_STATIC = YES",
        "GENERATE_HTML = YES",
        # Doxygen warns that a tool that LaTeX depends on (epstopdf) is
        # not available. Explicitly disable LaTeX to stop these warnings.
        "GENERATE_LATEX = NO",
        "GENERATE_XML = YES",
        "INCLUDE_GRAPH = NO",
        "MACRO_EXPANSION = YES",
        "PROJECT_NAME = Pigweed",
        # TODO: https://pwbug.dev/402489948 - Replace PW_ALLOCATOR_HAS_ATOMICS
        # when `pw_atomic` provides portable atomics.
        """PREDEFINED = __cplusplus=202002L \\
                        PW_LOCKABLE= \\
                        PW_PRINTF_FORMAT(...)= \\
                        PW_CONSTEXPR_CPP20= \\
                        PW_EXCLUSIVE_LOCK_FUNCTION(...)= \\
                        PW_EXCLUSIVE_TRYLOCK_FUNCTION(...)= \\
                        PW_UNLOCK_FUNCTION(...)= \\
                        PW_NO_LOCK_SAFETY_ANALYSIS= \\
                        PW_CXX_STANDARD_IS_SUPPORTED(...)=1 \\
                        PW_EXTERN_C_START= \\
                        PW_LOCKS_EXCLUDED(...)= \\
                        PW_EXCLUSIVE_LOCKS_REQUIRED(...)= \\
                        PW_GUARDED_BY(...)= \\
                        PW_NO_SANITIZE(...)= \\
                        PW_NODISCARD_STR(...)= \\
                        PW_ALLOCATOR_HAS_ATOMICS=1 \\
                        configSUPPORT_STATIC_ALLOCATION=1 \\
                        configUSE_TIMERS=1 \\
                        configCHECK_FOR_STACK_OVERFLOW=1 \\
                        PW_EXCLUDE_FROM_DOXYGEN=1""",
        "QUIET = YES",  # Don't log informational messages.
        "RECURSIVE = YES",
        # TODO: https://pwbug.dev/393634135 - Fix all Doxygen warnings.
        "WARN_LOGFILE = doxygen_build_logs.txt",
    ],
    tags = ["manual"],
    # Don't use rules_doxygen's `aliases` attribute. Define aliases within
    # `configurations`. The `aliases` attribute doesn't render aliases with
    # args correctly: https://github.com/TendTo/rules_doxygen/issues/12
    # aliases = []
    target_compatible_with = incompatible_with_mcu(),
)

filegroup(
    name = "_doxygen_html_1",
    srcs = [":doxygen_build"],
    output_group = "html",
    tags = ["manual"],
    target_compatible_with = incompatible_with_mcu(),
)

copy_directory(
    name = "_doxygen_html_2",
    src = ":_doxygen_html_1",
    out = "doxygen",
    tags = ["manual"],
)

sphinx_docs_library(
    name = "doxygen_html",
    srcs = [":_doxygen_html_2"],
    prefix = "doxygen/",
    tags = ["manual"],
    target_compatible_with = incompatible_with_mcu(),
)

filegroup(
    name = "_doxygen_xml",
    srcs = [":doxygen_build"],
    output_group = "xml",
    tags = ["manual"],
    target_compatible_with = incompatible_with_mcu(),
)

sphinx_docs_library(
    name = "doxygen_xml",
    srcs = [":_doxygen_xml"],
    prefix = "_doxygen/",
    tags = ["manual"],
    target_compatible_with = incompatible_with_mcu(),
)

sphinx_build_binary(
    name = "sphinx_build",
    tags = ["manual"],
    target_compatible_with = incompatible_with_mcu(),
    deps = [
        "//pw_build/py:pigweed_upstream_build",
        "//pw_build/py:pw_build",
        "//pw_build/py:pw_project_builder",
        "//pw_console/py:pw_console",
        "//pw_containers/py:inline_var_len_entry_queue",
        "//pw_docgen/py:pw_docgen",
        "//pw_emu/py:pw_emu",
        "//pw_env_setup/py:pw_env_setup",
        "//pw_env_setup/py:pw_env_setup_private",
        "//pw_hdlc/py:pw_hdlc",
        "//pw_ide/py:pw_ide",
        "//pw_log/py:pw_log",
        "//pw_log_rpc/py:pw_log_rpc",
        "//pw_presubmit/py:pw_presubmit",
        "//pw_protobuf_compiler/py:pw_protobuf_compiler",
        "//pw_rpc/py:pw_rpc_benchmark",
        "//pw_status/py:pw_status",
        "//pw_system/py:device_sim",
        "//pw_system/py:pw_system_benchmark_runner",
        "//pw_system/py:pw_system_console",
        "//pw_system/py:pw_system_lib",
        "//pw_tokenizer/py:pw_tokenizer",
        "//pw_transfer/py:pw_transfer",
        "//pw_unit_test/py:pw_unit_test",
        "//pw_watch/py:pw_watch",
        "//pw_watch/py:watch",
        "@pigweed_python_packages//breathe",
        "@pigweed_python_packages//jsonschema",
        "@pigweed_python_packages//kconfiglib",
        "@pigweed_python_packages//pydata_sphinx_theme",
        "@pigweed_python_packages//pytz",
        "@pigweed_python_packages//sphinx",
        "@pigweed_python_packages//sphinx_argparse",
        "@pigweed_python_packages//sphinx_copybutton",
        "@pigweed_python_packages//sphinx_design",
        "@pigweed_python_packages//sphinx_reredirects",
        "@pigweed_python_packages//sphinxcontrib_mermaid",
        "@rules_python//python/runfiles",
    ],
)

# Use Sphinx to build the main pigweed.dev website.
#
# The main `docs` target must output a directory containing the fully
# built pigweed.dev website. It must output a directory, not an archive,
# because our deploy code expects a directory when it uploads the website
# code and assets to our CDN.
sphinx_docs(
    name = "docs",
    config = "conf.py",
    extra_opts = [
        "--silent",
        "--fail-on-warning",
        "--jobs",
        "16",
    ],
    formats = [
        "html",
    ],
    sphinx = ":sphinx_build",
    strip_prefix = "docs/",
    tags = ["manual"],
    target_compatible_with = incompatible_with_mcu(),
    deps = [
        ":doxygen_html",
        ":doxygen_xml",
        ":not_prefixed",
        ":prefixed",
        ":rust",
        "//:docs",
        "//docker:docs",
        "//kudzu:docs",
        "//pw_alignment:docs",
        "//pw_allocator:docs",
        "//pw_analog:docs",
        "//pw_android_toolchain:docs",
        "//pw_arduino_build:docs",
        "//pw_assert:docs",
        "//pw_assert_basic:docs",
        "//pw_assert_fuchsia:docs",
        "//pw_assert_log:docs",
        "//pw_assert_tokenized:docs",
        "//pw_assert_trap:docs",
        "//pw_assert_zephyr:docs",
        "//pw_async:docs",
        "//pw_async2:docs",
        "//pw_async2_basic:docs",
        "//pw_async2_epoll:docs",
        "//pw_async_basic:docs",
        "//pw_async_fuchsia:docs",
        "//pw_atomic:docs",
        "//pw_base64:docs",
        "//pw_bloat:docs",
        "//pw_blob_store:docs",
        "//pw_bluetooth:docs",
        "//pw_bluetooth_hci:docs",
        "//pw_bluetooth_profiles:docs",
        "//pw_bluetooth_proxy:docs",
        "//pw_bluetooth_sapphire:docs",
        "//pw_boot:docs",
        "//pw_boot_cortex_m:docs",
        "//pw_build:docs",
        "//pw_build_android:docs",
        "//pw_build_info:docs",
        "//pw_build_mcuxpresso:docs",
        "//pw_bytes:docs",
        "//pw_channel:docs",
        "//pw_checksum:docs",
        "//pw_chre:docs",
        "//pw_chrono:docs",
        "//pw_chrono_embos:docs",
        "//pw_chrono_freertos:docs",
        "//pw_chrono_rp2040:docs",
        "//pw_chrono_stl:docs",
        "//pw_chrono_threadx:docs",
        "//pw_chrono_zephyr:docs",
        "//pw_cli:docs",
        "//pw_cli_analytics:docs",
        "//pw_clock_tree:docs",
        "//pw_clock_tree_mcuxpresso:docs",
        "//pw_compilation_testing:docs",
        "//pw_config_loader:docs",
        "//pw_console:docs",
        "//pw_containers:docs",
        "//pw_cpu_exception:docs",
        "//pw_cpu_exception_cortex_m:docs",
        "//pw_cpu_exception_risc_v:docs",
        "//pw_crypto:docs",
        "//pw_digital_io:docs",
        "//pw_digital_io_linux:docs",
        "//pw_digital_io_mcuxpresso:docs",
        "//pw_digital_io_rp2040:docs",
        "//pw_digital_io_zephyr:docs",
        "//pw_display:docs",
        "//pw_dma_mcuxpresso:docs",
        "//pw_docgen:docs",
        "//pw_doctor:docs",
        "//pw_elf:docs",
        "//pw_emu:docs",
        "//pw_env_setup:docs",
        "//pw_env_setup_zephyr:docs",
        "//pw_file:docs",
        "//pw_flatbuffers:docs",
        "//pw_format:docs",
        "//pw_function:docs",
        "//pw_fuzzer:docs",
        "//pw_grpc:docs",
        "//pw_hdlc:docs",
        "//pw_hex_dump:docs",
        "//pw_i2c:docs",
        "//pw_i2c_linux:docs",
        "//pw_i2c_mcuxpresso:docs",
        "//pw_i2c_rp2040:docs",
        "//pw_i2c_zephyr:docs",
        "//pw_ide:docs",
        "//pw_interrupt:docs",
        "//pw_interrupt_cortex_m:docs",
        "//pw_interrupt_freertos:docs",
        "//pw_interrupt_zephyr:docs",
        "//pw_intrusive_ptr:docs",
        "//pw_json:docs",
        "//pw_kernel:docs",
        "//pw_kvs:docs",
        "//pw_libc:docs",
        "//pw_libcxx:docs",
        "//pw_log:docs",
        "//pw_log_android:docs",
        "//pw_log_basic:docs",
        "//pw_log_fuchsia:docs",
        "//pw_log_null:docs",
        "//pw_log_rpc:docs",
        "//pw_log_string:docs",
        "//pw_log_tokenized:docs",
        "//pw_log_zephyr:docs",
        "//pw_malloc:docs",
        "//pw_malloc_freelist:docs",
        "//pw_malloc_freertos:docs",
        "//pw_metric:docs",
        "//pw_minimal_cpp_stdlib:docs",
        "//pw_module:docs",
        "//pw_multibuf:docs",
        "//pw_multisink:docs",
        "//pw_numeric:docs",
        "//pw_package:docs",
        "//pw_perf_test:docs",
        "//pw_persistent_ram:docs",
        "//pw_polyfill:docs",
        "//pw_preprocessor:docs",
        "//pw_presubmit:docs",
        "//pw_protobuf:docs",
        "//pw_protobuf_compiler:docs",
        "//pw_random:docs",
        "//pw_random_fuchsia:docs",
        "//pw_result:docs",
        "//pw_ring_buffer:docs",
        "//pw_router:docs",
        "//pw_rpc:docs",
        "//pw_rpc_transport:docs",
        "//pw_rust:sphinx",
        "//pw_sensor:docs",
        "//pw_snapshot:docs",
        "//pw_software_update:docs",
        "//pw_span:docs",
        "//pw_spi:docs",
        "//pw_spi_linux:docs",
        "//pw_spi_mcuxpresso:docs",
        "//pw_spi_rp2040:docs",
        "//pw_status:docs",
        "//pw_stm32cube_build:docs",
        "//pw_stream:docs",
        "//pw_stream_shmem_mcuxpresso:docs",
        "//pw_stream_uart_linux:docs",
        "//pw_stream_uart_mcuxpresso:docs",
        "//pw_string:docs",
        "//pw_symbolizer:docs",
        "//pw_sync:docs",
        "//pw_sync_baremetal:docs",
        "//pw_sync_embos:docs",
        "//pw_sync_freertos:docs",
        "//pw_sync_stl:docs",
        "//pw_sync_threadx:docs",
        "//pw_sync_zephyr:docs",
        "//pw_sys_io:docs",
        "//pw_sys_io_ambiq_sdk:docs",
        "//pw_sys_io_arduino:docs",
        "//pw_sys_io_baremetal_lm3s6965evb:docs",
        "//pw_sys_io_baremetal_stm32f429:docs",
        "//pw_sys_io_emcraft_sf2:docs",
        "//pw_sys_io_mcuxpresso:docs",
        "//pw_sys_io_rp2040:docs",
        "//pw_sys_io_stdio:docs",
        "//pw_sys_io_stm32cube:docs",
        "//pw_sys_io_zephyr:docs",
        "//pw_system:docs",
        "//pw_target_runner:docs",
        "//pw_thread:docs",
        "//pw_thread_embos:docs",
        "//pw_thread_freertos:docs",
        "//pw_thread_stl:docs",
        "//pw_thread_threadx:docs",
        "//pw_thread_zephyr:docs",
        "//pw_tls_client:docs",
        "//pw_tls_client_boringssl:docs",
        "//pw_tls_client_mbedtls:docs",
        "//pw_tokenizer:docs",
        "//pw_toolchain:docs",
        "//pw_trace:docs",
        "//pw_trace_tokenized:docs",
        "//pw_transfer:docs",
        "//pw_uart:docs",
        "//pw_uart_mcuxpresso:docs",
        "//pw_unit_test:docs",
        "//pw_uuid:docs",
        "//pw_varint:docs",
        "//pw_watch:docs",
        "//pw_web:docs",
        "//pw_work_queue:docs",
        "//seed:docs",
        "//targets:docs",
        "//third_party:docs",
    ],
)
